// 添加spawn导入
import { spawn } from 'child_process'
import { join } from 'path'
// import { fileURLToPath } from 'url'
// import { dirname } from 'path'
import fs from 'fs'
import { BrowserWindow } from 'electron'
import { StreamConfigManager } from './stream-config-manager.js'
import appConfig from '../config/app-config.js'

// 为ES模块提供__dirname和__filename
// const __filename = fileURLToPath(import.meta.url)
// const __dirname_local = dirname(__filename)

const streamConfigManager = new StreamConfigManager()
// const windows = require('electron').BrowserWindow.getAllWindows()
const windows = BrowserWindow.getAllWindows()

// 获取FFmpeg可执行文件路径
const getFfmpegPath = () => {
  // 开发环境：使用项目中的ffmpeg-bin目录
  // const devPath = join(__dirname_local, '..', '..', 'ffmpeg-bin', 'ffmpeg.exe')

  // // 生产环境：使用打包后的路径（ffmpeg.exe会被复制到dist/main目录）
  // const prodPath = join(__dirname_local, 'ffmpeg.exe')

  // // 检查开发环境路径是否存在
  // if (fs.existsSync(devPath)) {
  //   console.log('使用开发环境FFmpeg路径:', devPath)
  //   return devPath
  // }

  // // 检查生产环境路径是否存在
  // if (fs.existsSync(prodPath)) {
  //   console.log('使用生产环境FFmpeg路径:', prodPath)
  //   return prodPath
  // }

  // // 如果都找不到，尝试使用系统PATH中的ffmpeg
  // console.warn('未找到项目中的FFmpeg二进制文件，将尝试使用系统PATH中的ffmpeg')
  return 'ffmpeg'
}

class FfmpegManager {
  constructor() {
    this.processes = new Map() // 存储每个流的FFmpeg进程
    this.outputDirs = new Map() // 存储每个流的输出目录
    this.ffmpegPath = getFfmpegPath() // 获取FFmpeg路径
    this.monitors = new Map() // 存储每个流的监控定时器
    this.restartAttempts = new Map() // 存储每个流的重启尝试次数
    this.maxRestartAttempts = 3 // 最大重启尝试次数
    this.checkInterval = 5000 // 检查间隔时间(毫秒)
    this.restartTimers = new Map() // 添加：存储每个流的重启计时器
  }

  // 启动FFmpeg转码
  startStream(streamConfig) {
    // 获取所有窗口引用

    // 如果 streamConfig 为空，或者缺少必要字段，返回失败
    if (!streamConfig || !streamConfig.id || !streamConfig.name || !streamConfig.rtsp) {
      windows.forEach((window) => {
        window.webContents.send(
          'addLog',
          `[ERROR] 启动FFmpeg转码服务失败，配置不完整: ${JSON.stringify(streamConfig)}`
        )
      })
      return false
    }

    const { id, name, rtsp } = streamConfig

    windows.forEach((window) => {
      window.webContents.send('addLog', `FFMPEG-Manager [INFO] 启动FFmpeg转码服务，RTSP: ${rtsp}`)
    })

    // 检查是否已经在运行
    if (this.processes.has(id)) {
      console.log(`流 ${name} 已经在运行中`)
      return false
    }

    // 创建输出目录
    // const outputDir = join(__dirname_local, 'hls_output')
    console.log('工作区路径:', appConfig.workspacePath)
    console.log('HLS输出路径:', appConfig.rtsp2hlsConfig.hls.outputDir)
    console.log('流ID:', id)
    const outputDir = join(appConfig.workspacePath, appConfig.rtsp2hlsConfig.hls.outputDir, id)
    console.log(`输出目录: ${outputDir}`)
    if (!fs.existsSync(outputDir)) {
      fs.mkdirSync(outputDir, { recursive: true })
    }
    this.outputDirs.set(id, outputDir)

    try {
      const ffmpegArgs = [
        '-rtsp_transport',
        'udp', // 输入RTSP流
        '-i',
        rtsp,
        '-c',
        'copy', // 直接复制流，不进行重新编码
        '-f',
        'hls', // 输出格式为HLS
        '-hls_time',
        '8', // 每个TS文件时长8秒
        '-hls_list_size',
        '5', // 播放列表包含5个片段
        '-hls_flags',
        'delete_segments', // 自动删除旧片段
        '-hls_segment_filename',
        join(outputDir, `%03d.ts`), // TS文件命名
        join(outputDir, `play.m3u8`) // 主播放列表文件
      ]

      console.log('m3u8 path: ', join(outputDir, `play.m3u8`))

      console.log('启动FFmpeg命令:', this.ffmpegPath, ffmpegArgs.join(' '))
      console.log('FFmpeg路径:', this.ffmpegPath)

      // 启动FFmpeg进程（使用正确的路径）
      const ffmpegProcess = spawn(this.ffmpegPath, ffmpegArgs, {
        stdio: ['pipe', 'pipe', 'pipe'],
        windowsHide: true // 在Windows上隐藏子进程窗口
      })

      // 存储进程引用
      this.processes.set(id, ffmpegProcess)
      // 重置重启计数器
      this.restartAttempts.set(id, 0)

      // 处理标准输出
      ffmpegProcess.stdout.on('data', (data) => {
        console.log(`FFmpeg stdout [${name}]:`, data.toString())
      })

      // 处理标准错误（FFmpeg的主要输出）
      ffmpegProcess.stderr.on('data', (data) => {
        const output = data.toString()
        // console.log(`FFmpeg stderr [${name}]:`, output)

        // 发送日志到渲染进程
        windows.forEach((window) => {
          window.webContents.send('addLog', `[FFMPEG ${name}] ${output}`)
        })
      })

      // 处理进程退出
      ffmpegProcess.on('close', (code) => {
        console.log(`FFmpeg进程 [${name}] 退出，代码: ${code}`)
        this.processes.delete(id)

        // 如果不是手动停止，尝试重启
        if (this.monitors.has(id)) {
          this.attemptRestart(id, streamConfig, code)
        } else {
          this.outputDirs.delete(id)

          // 发送状态更新
          windows.forEach((window) => {
            window.webContents.send('addLog', `[INFO] 流 ${name} 已停止`)
          })
        }
      })

      // 处理进程错误
      ffmpegProcess.on('error', (error) => {
        console.error(`!!!!! FFmpeg进程 [${name}] 错误:`, error)
        this.processes.delete(id)

        // 确保只发送字符串，而不是对象
        const errorMessage =
          typeof error === 'object' ? error.message || JSON.stringify(error) : error.toString()

        // 如果不是手动停止，尝试重启
        if (this.monitors.has(id)) {
          this.attemptRestart(id, streamConfig, null, error)
        } else {
          this.outputDirs.delete(id)

          windows.forEach((window) => {
            window.webContents.send('addLog', `[ERROR] 流 ${name} 启动失败: ${errorMessage}`)
          })
        }
      })

      // 启动监控
      this.startMonitoring(id, streamConfig)

      const httpPort = appConfig.httpServerConfig.runningPort
      const hlsUrl = `http://localhost:${httpPort}/hls/${id}/play.m3u8`

      console.log(`FFmpeg 转码服务已启动: ${name} -> ${hlsUrl}`)

      const response = {
        success: true,
        id,
        name,
        outputDir,
        hlsUrl: hlsUrl,
        status: 'running',
        message: `HLSURL: ${name} -> ${hlsUrl}`
      }

      return response
    } catch (error) {
      console.error(`启动FFmpeg转码失败 [${name}]:`, error)

      // 确保只发送字符串
      const errorMessage =
        typeof error === 'object' ? error.message || JSON.stringify(error) : error.toString()

      windows.forEach((window) => {
        window.webContents.send('addLog', `[ERROR] 启动流 ${name} 失败: ${errorMessage}`)
      })
      return {
        success: false,
        message: `启动流 ${name} 失败: ${errorMessage}`
      }
    }
  }

  // 启动监控
  startMonitoring(streamId, streamConfig) {
    const { name } = streamConfig

    // 设置定期检查定时器
    const monitorInterval = setInterval(() => {
      this.checkStreamStatus(streamId, streamConfig)
    }, this.checkInterval)

    this.monitors.set(streamId, monitorInterval)
    console.log(`启动流监控: ${name}`)
  }

  // 检查流状态
  checkStreamStatus(streamId, streamConfig) {
    const { name } = streamConfig
    const process = this.processes.get(streamId)

    // 检查进程是否存在且正常运行
    if (!process || !this.isProcessAlive(process.pid)) {
      console.warn(`!!!!! 流 ${name} 进程异常，尝试重启...`)
      this.attemptRestart(streamId, streamConfig)
    }
  }

  // 尝试重启流
  attemptRestart(streamId, streamConfig, exitCode = null, error = null) {
    const { name } = streamConfig
    const currentAttempts = this.restartAttempts.get(streamId) || 0

    // 检查是否超过最大重启次数
    if (currentAttempts >= this.maxRestartAttempts) {
      console.error(`流 ${name} 已达到最大重启次数(${this.maxRestartAttempts})，停止尝试`)

      // 发送通知到渲染进程
      windows.forEach((window) => {
        window.webContents.send(
          'addLog',
          `[ERROR] 流 ${name} 已达到最大重启次数，停止服务。请检查RTSP源或FFmpeg配置。`
        )
      })

      // 清除监控
      this.stopMonitoring(streamId)
      this.outputDirs.delete(streamId)
      return
    }

    // 增加重启计数
    this.restartAttempts.set(streamId, currentAttempts + 1)

    // 清除之前所有的 settimeout 实例
    // 修复：清除之前所有的重启计时器
    if (this.restartTimers.has(streamId)) {
      clearTimeout(this.restartTimers.get(streamId))
      this.restartTimers.delete(streamId)
    }

    // 等待一小段时间后重启
    const restartTimer = setTimeout(() => {
      // 移除当前重启计时器的记录
      this.restartTimers.delete(streamId)

      // 再次检查流是否真的需要重启（避免竞争条件）
      if (this.processes.has(streamId)) {
        console.log(`流 ${name} 已经在运行中，取消重启尝试`)
        return
      }
      console.log(`尝试重启流 ${name} (第 ${currentAttempts + 1}/${this.maxRestartAttempts} 次)`)

      // 发送通知到渲染进程
      windows.forEach((window) => {
        const restartMsg = `[INFO] 尝试重启流 ${name} (第 ${currentAttempts + 1}/${this.maxRestartAttempts} 次)`
        window.webContents.send('addLog', restartMsg)

        if (error) {
          const errorMessage =
            typeof error === 'object' ? error.message || JSON.stringify(error) : error.toString()
          window.webContents.send('addLog', `[ERROR] 重启原因: ${errorMessage}`)
        } else if (exitCode !== null) {
          window.webContents.send('addLog', `[ERROR] 重启原因: 进程意外退出，退出码: ${exitCode}`)
        }
      })

      // 尝试重新启动流
      this.startStream(streamConfig)
    }, 2000) // 延迟2秒后重启

    // 保存重启计时器引用
    this.restartTimers.set(streamId, restartTimer)
  }

  // 检查进程是否存活
  isProcessAlive(pid) {
    try {
      // 在Windows上检查进程是否存在
      process.kill(pid, 0)
      return true
    } catch (error) {
      console.log(`进程 ${pid} 不存在, error:${error.message}`)
      return false
    }
  }

  // 停止监控

  stopMonitoring(streamId) {
    const monitor = this.monitors.get(streamId)
    if (monitor) {
      clearInterval(monitor)
      this.monitors.delete(streamId)
      this.restartAttempts.delete(streamId)

      // 修复：同时清除重启计时器
      if (this.restartTimers.has(streamId)) {
        clearTimeout(this.restartTimers.get(streamId))
        this.restartTimers.delete(streamId)
      }
    }
  }

  // 停止FFmpeg转码
  stopStream(streamId) {
    const process = this.processes.get(streamId)
    if (process) {
      // 清除监控
      this.stopMonitoring(streamId)

      process.kill('SIGTERM') // 优雅终止
      this.processes.delete(streamId)
      console.log(`FFmpeg转码服务已停止: ${streamId}`)
      windows.forEach((window) => {
        window.webContents.send('addLog', `[INFO] 流 ${streamId} 已停止`)
      })
      // 删除输出目录（可选），删除 id. 或者 id_ 开头的文件
      const outputDir = this.outputDirs.get(streamId)
      if (outputDir) {
        try {
          fs.readdirSync(outputDir).forEach((file) => {
            if (file.startsWith(`${streamId}.`) || file.startsWith(`${streamId}_`)) {
              fs.unlinkSync(join(outputDir, file))
            }
          })
        } catch (err) {
          console.error(`删除输出目录 ${outputDir} 时出错: ${err.message}`)
        }
      }
      this.outputDirs.delete(streamId)

      return true
    }
    windows.forEach((window) => {
      window.webContents.send('addLog', `[INFO] 流 ${streamId} 不存在，无法停止！`)
    })
    return false
  }

  stopAllStreams() {
    // 清除所有监控
    this.monitors.forEach((monitor) => clearInterval(monitor))
    this.monitors.clear()
    this.restartAttempts.clear()

    // 修复：清除所有重启计时器
    this.restartTimers.forEach((timer) => clearTimeout(timer))
    this.restartTimers.clear()

    this.processes.forEach((process) => {
      process.kill('SIGTERM')
    })
    this.processes.clear()
    this.outputDirs.clear()
    // 将所有流配置设为停止状态
    streamConfigManager.setAllStreamsToStopped()
    console.log('所有FFmpeg转码服务已停止')

    windows.forEach((window) => {
      window.webContents.send('addLog', `[INFO] 所有流转码服务已停止`)
    })
  }

  // 检查流是否在运行
  isStreamRunning(streamId) {
    return this.processes.has(streamId)
  }

  // 获取所有运行中的流
  getRunningStreams() {
    return Array.from(this.processes.keys())
  }
}

export { FfmpegManager }
